﻿#pragma once
#include "OCGrib/GribReader.h"
#include "OCMain/FileUtil.h"
#include "OCMain/Log.h"
#include "OCNetCDF/NetCDFReader.h"
#include "OCNetCDF/NetcdfExtract.h"
#include "OCVolume/VolumeEncoder.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include <regex>

using namespace OCPP;

//颠簸指数
void  ExtractGrib0()
{
	int knownMaxLevelIndex = 10;

	String dataPath = "e:/mao/93";
	String output = "E:/OCServer250901/tmp";
	//String output = "D:/opt/93保障";
	//String dataPath = output;

#if 1
	{
		String subDataPath = joinPath(dataPath, "uv");
		auto files = FileUtil::findFiles(U2A(subDataPath));
		for (const auto& f : files)
		{
			String name, ext, path;
			StringUtil::splitFullFilename(f, name, ext, path);
			StringUtil::toLowerCase(ext);
			if (ext != "nc") continue;
			String fileName = joinPath(subDataPath, f);
			OCPP_LOG_INFO << fileName << "\n";
			VolumeOptions options;
			options.knownLevelUnits = "m";
			options.customClipExtent = Cesium::Rectangle::fromDegrees(115.28, 37.9, 120.5, 41.1);
			options.nameDimZ = { "lev" };
			options.setWriter(new VolumeD3Writer());
			options.getWriter().setGZipCompress(true);
			options.getWriter().setOutputPath(U2A(output));
			options.knownMaxLevelIndex = knownMaxLevelIndex;
			options.getWriter().customOutputName = name;
			GridDataCompute gridDataCompute;
			gridDataCompute.add({ U2A(fileName), "uu_3" });
			gridDataCompute.add({ U2A(fileName), "vv_3" });
			NetcdfExtract::computeAndExtract3D(gridDataCompute, options);
		}
	}
#endif


#if 1
	{
		String subDataPath = joinPath(dataPath, "cloud");
		auto files = FileUtil::findFiles(U2A(subDataPath));
		for (const auto& f : files)
		{
			String name, ext, path;
			StringUtil::splitFullFilename(f, name, ext, path);
			StringUtil::toLowerCase(ext);
			if (ext != "nc") continue;
			String fileName = joinPath(subDataPath, f);
			VolumeOptions options;
			options.knownLevelUnits = "m";
			options.customClipExtent = Cesium::Rectangle::fromDegrees(115.28, 37.9, 120.5, 41.1);
			options.nameDimZ = { "lev" };
			options.setWriter(new VolumeD3Writer());
			options.getWriter().setGZipCompress(true);
			options.getWriter().setOutputPath(U2A(output));
			options.getWriter().customOutputName = name;
			NetcdfExtract::extract3D(U2A(fileName), "cloud_3", options);
		}
	}
#endif

#if 1
	{
		String subDataPath = joinPath(dataPath, "shr");
		auto files = FileUtil::findFiles(U2A(subDataPath));
		for (const auto& f : files)
		{
			String name, ext, path;
			StringUtil::splitFullFilename(f, name, ext, path);
			StringUtil::toLowerCase(ext);
			if (ext != "nc") continue;
			String fileName = joinPath(subDataPath, f);
			VolumeOptions options;
			options.knownIsPositive = true;
			options.knownMaxLevelIndex = knownMaxLevelIndex;
			options.knownLevelUnits = "m";
			options.customClipExtent = Cesium::Rectangle::fromDegrees(115.28, 37.9, 120.5, 41.1);
			options.nameDimZ = { "lev" };
			options.setWriter(new VolumeD3Writer());
			options.getWriter().setGZipCompress(true);
			options.getWriter().setOutputPath(U2A(output));
			options.getWriter().customOutputName = name;
			NetcdfExtract::extract3D(U2A(fileName), "shr_3", options);
		}
	}
#endif

#if 1
	{
		String subDataPath = joinPath(dataPath, "EDR");
		auto files = FileUtil::findFiles(U2A(subDataPath));
		for (const auto& f : files)
		{
			String name, ext, path;
			StringUtil::splitFullFilename(f, name, ext, path);
			StringUtil::toLowerCase(ext);
			if (ext != "nc") continue;
			String fileName = joinPath(subDataPath, f);
			VolumeOptions options;
			options.customReverseZ = true;
			options.knownLevelUnits = "m";
			//options.customClipExtent = Cesium::Rectangle::fromDegrees(115.28, 37.9, 120.5, 41.1);
			options.nameDimX = { "lon_all" };
			options.nameDimY = { "lat_all" };
			options.nameDimZ = { "lev" };
			options.setWriter(new VolumeD3Writer());
			options.getWriter().setGZipCompress(true);
			options.getWriter().setOutputPath(U2A(output));
			options.getWriter().customOutputName = name;
			NetcdfExtract::extract3D(U2A(fileName), "all_edr", options);
		}
	}
#endif
}

//gfs grid
void  ExtractGrib4()
{
	String output = "D:\\opt\\gfs";
	String fileName = "D:\\opt\\gfs\\20250816010000.grib";

	VolumeOptions options;
	options.customReverseZ = true;
	options.setWriter(new VolumeD3Writer());
	options.getWriter().setMakeDirForFile(true);
	options.getWriter().setDimSeperator("_");
	options.getWriter().setOutputPath(U2A(output));
	options.getWriter().setGZipCompress(true);
	//NetcdfExtract::extract3D(fileName, "Temperature_height_above_ground", options);

	{
		NetcdfExtract::extract2D(fileName, "Temperature_height_above_ground", options, 0);
	}

	//{
	//	GridDataCompute gridDataCompute;
	//	gridDataCompute.add({ U2A(fileName), "u-component_of_wind_height_above_ground" });
	//	gridDataCompute.add({ U2A(fileName), "v-component_of_wind_height_above_ground" });
	//	NetcdfExtract::computeAndExtract2D(gridDataCompute, options, 0);
	//}

	//{
	//	GridDataCompute gridDataCompute;
	//	gridDataCompute.add({ U2A(fileName), "u-component_of_wind_isobaric" });
	//	gridDataCompute.add({ U2A(fileName), "v-component_of_wind_isobaric" });
	//	NetcdfExtract::computeAndExtract2D(gridDataCompute, options, 40);
	//	NetcdfExtract::computeAndExtract3D(gridDataCompute, options);
	//}
}

//研究室低空风场
void  ExtractGrib()
{
	String output = "D:\\opt\\低空风场\\风场3";
	String fileName = "D:\\opt\\低空风场\\风场3\\Z_NAFP_C_BABJ_20251030170740_P_3DWind_RT_BCWHDH_5m_5MIN-MUL-.nc";

	VolumeOptions options;
	options.knownLevelUnits = "m";
	options.knownMaxLevelIndex = 53;
	//options.knownMaxLevelIndex = 22;
	options.customScaler = 0.01f;
	options.knownNotLonLat = true;
	options.preferHalfFloat = true;
	//float dx = 5.0;
	//options.customClipExtent = Cesium::Rectangle::fromDegrees(735311.01 + dx * 61.0f, 2554796.460, 745546.841 + dx * 60.0f, 2561034.993);
	options.setWriter(new VolumeD3Writer());
	options.getWriter().setOutputPath(U2A(output));
	options.getWriter().setGZipCompress(false);
	
	options.getWriter().customOutputName = "高新53m";

	GridDataCompute gridDataCompute;
	gridDataCompute.add({ U2A(fileName), "UWIND" });
	gridDataCompute.add({ U2A(fileName), "VWIND" });
	gridDataCompute.add({ U2A(fileName), "WWIND" });
	NetcdfExtract::computeAndExtract3D(gridDataCompute, options);
	//NetcdfExtract::computeAndExtract2D(gridDataCompute, options, 0);
}

void  ExtractGrib3()
{
	String output = "D:\\opt\\垂直观测\\X波段output";
	//String dir = "D:\\opt\\垂直观测\\0805天津城市内涝数字孪生\\2025070210_11";
	String dir = "D:\\opt\\垂直观测\\0805天津城市内涝数字孪生\\2025070214_15";

	using DateTimeMap = std::map<String, String>;

	DateTimeMap dateTimeMap;
	auto files = FileUtil::findFiles(U2A(dir));
	for (const auto& f : files)
	{
		if (f == "." || f == "..")continue;
		const std::regex pattern(R"(Z_RADA_C_BABJ_(\d{14})_P_DOR_TJ_MCAP_(\d{8}_\d{6})_(\d{2}).bin)");
		std::smatch match;
		std::regex_match(f, match, pattern);
		if (match.size() == 4)
		{
			String dateTime = match[2].str();
			dateTimeMap[dateTime] = match[1].str();
		}
	}

	OCPP_LOG_INFO << "Total:" << dateTimeMap.size() << "\n";
	for (const auto& [dateTime, productTime] : dateTimeMap)
	{
		String customOutputName = StringUtil::replaceAll(dateTime, "_", "");
		String outFileName = joinPath(output, customOutputName + ".bin");

		if (FileUtil::existFile(U2A(outFileName)))
		{
			continue;
		}

		OCPP_LOG_INFO << "DateTime:" << dateTime << "\n";

		VolumeOptions options;
		options.customClipExtent = Cesium::Rectangle::fromDegrees(116.35f, 38.35, 118.35f, 40.35);
		options.knownLevelUnits = "m";
		options.setWriter(new VolumeD3Writer());
		options.getWriter().setMakeDirForFile(true);
		options.getWriter().setOutputPath(U2A(output));
		options.getWriter().setGZipCompress(false);
		options.getWriter().customOutputName = customOutputName;

		GridDataCompute gridDataCompute;
		gridDataCompute.setAlgorithm(new GridDataAlgorithmFloor());

		bool error = false;
		for (int i = 0; i < 24; i++)
		{
			String fileName = joinPath(dir,
				str_format("Z_RADA_C_BABJ_%s_P_DOR_TJ_MCAP_%s_%02d.bin",
					productTime.c_str(),
					dateTime.c_str(), i));

			if (!FileUtil::existFile(U2A(fileName)))
			{
				OCPP_LOG_ERROR << dateTime << "\n";
				error = true;
				break;
			}
			gridDataCompute.add({ U2A(fileName), "" });
		}
		if (!error)
		{
			NetcdfExtract::computeAndExtract3D(gridDataCompute, options);
		}
		//break;
	}
}

//广东低空风场
void ExtractGrib2()
{
	String fileName = "D:/opt/广州低空/uvwrho-guangzhouR_20250910105000_visluw.nc";
	String output = "D:/opt/广州低空";

	VolumeOptions options;
	options.customFindLonLat = true;
	options.knownLevelUnits = "m";
	options.setWriter(new VolumeD3Writer());
	options.getWriter().setOutputPath(U2A(output));
	options.getWriter().setGZipCompress(false);

	GridDataCompute gridDataCompute;
	gridDataCompute.add({ U2A(fileName), "u_grid" });
	gridDataCompute.add({ U2A(fileName), "v_grid" });
	gridDataCompute.add({ U2A(fileName), "w" });
	NetcdfExtract::computeAndExtract3D(gridDataCompute, options);
	//NetcdfExtract::computeAndExtract2D(gridDataCompute, options, 10);
	//NetcdfExtract::extract2D(U2A(fileName), "u_grid", options, 0);
}